﻿using Future.IService;
using Future.Web.Utility;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Text;

namespace Future.Web.Filter
{
    /// <summary>
    /// 缓存请求
    /// </summary>
    [AttributeUsage(AttributeTargets.Method)]
    public class RequestCacheFilter : Attribute, IActionFilter
    {
        private string _key = string.Empty;

        /// <summary>
        /// 缓存时间分钟
        /// </summary>
        public int ExpirationTime { get; set; }

        /// <summary>
        /// 构造方法
        /// </summary>
        /// <param name="expirationTime"></param>
        public RequestCacheFilter(int expirationTime = 0)
        {
            ExpirationTime = expirationTime;
        }

        /// <summary>
        /// action执行后缓存结果
        /// </summary>
        /// <param name="context"></param>
        public void OnActionExecuted(ActionExecutedContext context)
        {
            if (string.IsNullOrEmpty(_key))
            {
                return;
            }
            ICacheService? cacheService = GlobalContext.ServiceProvider.GetService<ICacheService>();
            if (cacheService == null)
            {
                return;
            }

            if (context.Result != null)
            {
                if (ExpirationTime > 0)
                {
                    cacheService.SetObject<object>(_key, context.Result, ExpirationTime);
                }
                else
                {
                    cacheService.SetObject<object>(_key, context.Result);
                }
            }
        }

        /// <summary>
        /// action执行前查缓存
        /// </summary>
        /// <param name="context"></param>
        public void OnActionExecuting(ActionExecutingContext context)
        {
            _key = ComposeKey(context.ActionArguments);
            if (string.IsNullOrEmpty(_key))
            {
                return;
            }
            _key = _key.ToLower();
            ICacheService? cacheService = GlobalContext.ServiceProvider.GetService<ICacheService>();
            if (cacheService == null)
            {
                return;
            }
            IActionResult? result = cacheService.GetObject<ObjectResult>(_key);
            if (result != null)
            {
                context.Result = result;
            }
        }

        /// <summary>
        /// 组合key
        /// </summary>
        /// <param name="actionArguments"></param>
        /// <returns></returns>
        private static string ComposeKey(IDictionary<string, object?> actionArguments)
        {
            StringBuilder sb = new();
            foreach (KeyValuePair<string, object?> item in actionArguments)
            {
                if (item.Value is not null && CheckType(item.Value.GetType()))
                {
                    sb.Append(item.Key);
                    sb.Append(item.Value.ToString());
                }
            }
            return sb.ToString();
        }

        /// <summary>
        /// 检查请求参数类型 只有string和int类型做缓存key 其他类型不用
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private static bool CheckType(Type type)
        {
            if (type == typeof(string) || type == typeof(int))
            {
                return true;
            }
            return false;
        }
    }
}
